package com.sharer.last.wrapper;

import com.sharer.last.base.utils.ConvertUtil;
import com.sharer.last.interfaces.TailRecursion;
import com.sharer.last.base.support.BaseEntityWrapper;
import com.sharer.last.model.po.CommentPO;
import com.sharer.last.model.vo.blog.BlogIdAndTitleVO;
import com.sharer.last.model.vo.comment.CommentVO;
import com.sharer.last.service.BlogService;
import com.sharer.last.service.CommentService;
import com.sharer.last.utils.BeanUtil;
import com.sharer.last.base.utils.CollectionUtil;
import com.sharer.last.utils.TailInvokeUtil;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 文件注释地方
 *
 * @ClassName CommentWrapper
 * @Author WangJin
 * @Date 2023/06/09/10:41
 * @Description
 * @Version 1.0
 */
@Component
public class CommentWrapper extends BaseEntityWrapper<CommentPO, CommentVO> {
    @Resource
    CommentService commentService;

    @Resource
    BlogService blogService;

    /**
     * 单个实体类包装
     *
     * @param entity
     * @return
     */
    @Override
    public CommentVO entityVO(CommentPO entity) {
        CommentVO       vo   = BeanUtil.copy(entity, CommentVO.class);
        List<CommentVO> list = new ArrayList<>();
        list.add(vo);
        TailRecursion<List<CommentVO>> res    = this.getChildrenComment(list, new ArrayList<>());
        List<CommentVO>                invoke = res.invoke();
        return invoke.get(0);
    }

    public List<CommentVO> toVO(List<CommentPO> entityList) {
        List<Long> relevantIdList = entityList.stream()
                .filter(f -> ConvertUtil.toInt(f.getRelevantId()) > 0)
                .map(CommentPO::getRelevantId).collect(Collectors.toList());
        Map<Long, BlogIdAndTitleVO> voMap = blogService.selectBlogTitleAndIdList(relevantIdList);

        return entityList.stream().map(item -> {
            CommentVO commentVO   = BeanUtil.copy(item, CommentVO.class);
            Long      relevantId  = commentVO.getRelevantId();
            Integer   commentType = commentVO.getCommentType();
            if (commentType == 1 && ConvertUtil.toInt(relevantId) > 0) {
                BlogIdAndTitleVO blogIdAndTitleVO = Optional.ofNullable(voMap.get(item.getId())).orElse(new BlogIdAndTitleVO());
                commentVO.setBlog(blogIdAndTitleVO);
            }
            return commentVO;
        }).collect(Collectors.toList());

    }

    /**
     * 递归获取下级评论
     *
     * @param entityList 父级评论
     * @return
     */
    public List<CommentVO> listVO(List<CommentPO> entityList) {
        List<CommentVO> list = this.toVO(entityList);

        TailRecursion<List<CommentVO>> res = this.getChildrenComment(list, new ArrayList<>());
        return res.invoke();
    }

    /**
     * <h3>获取下级评论</h3>
     * <p>利用Java引用传递的特性，一层一层的插入当前评论下的所有下级评论；并递归下级评论，从而获取下级评论的下级评论。。。</p>
     * <p>尾递归 尾递归优化 注：Java编译器对尾递归写法没有优化，所以需要自行实现尾递归优化</p>
     *
     * @param entityList 父级评论
     * @param children   下级评论
     * @return
     */
    private TailRecursion<List<CommentVO>> getChildrenComment(List<CommentVO> entityList, List<CommentVO> children) {
        List<CommentVO> invokeList;
        // 判断是否为第一次调用
        if (CollectionUtil.isEmpty(children)) {
            invokeList = entityList;
        } else {
            invokeList = children;
        }
        // 第一步 插入当前评论下的所有下级评论
        List<CommentVO> tempList = new ArrayList<>();
        for (CommentVO commentVO : invokeList) {
            Long            id        = commentVO.getId();
            List<CommentVO> childList = commentService.selectListById(id);
            if (CollectionUtil.isNotEmpty(childList)) {
                commentVO.setChildren(childList);
                tempList.addAll(childList);
            }
        }
        // 第二步 递归下级评论
        if (CollectionUtil.isNotEmpty(tempList)) {
            return TailInvokeUtil.call(getChildrenComment(entityList, tempList));
        } else {
            // 已经递归到最底层，将最初的集合返回
            return TailInvokeUtil.done(entityList);
        }
    }
}
